package com.ygqh.baby.controller;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.QueryInfo;
import com.ygqh.baby.ao.ResultSet;
import com.ygqh.baby.model.ChatRecord;
import com.ygqh.baby.model.ProcessUserReport;
import com.ygqh.baby.model.ProcessUserReportWrapper;
import com.ygqh.baby.service.ChatRecordService;
import com.ygqh.baby.service.ProcessUserReportService;
import com.ygqh.baby.utils.DateConvertUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

/**
 * @Author: sunshuo
 * @Date: 2019/9/18/018 10:47
 * @Version: 1.0
 */
@Controller
@RequestMapping("chat/report")
public class ReportController extends BaseController {

    @Autowired
    private ChatRecordService chatRecordService;
    @Autowired
    private ProcessUserReportService processUserReportService;

    /**
     * 接待用户数列表
     *
     * @param queryInfo 分页
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param callback callback
     * @return
     */
    @RequestMapping("userReport")
    @ResponseBody
    public JSONPObject userReport(QueryInfo queryInfo,
                                  @DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date startDate,
                                  @DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date endDate,
                                  String callback) {
        if (endDate != null) {
            endDate = DateConvertUtils.addDay(endDate, 1);
        }
        ResultSet<ProcessUserReport> resultSet = processUserReportService.search(queryInfo, startDate, endDate);
        return new JSONPObject(callback, Message.success(resultSet.toDatatables(null)));
    }

    /**
     * 接待用户数列表
     *
     * @param callback callback
     * @return
     */
    @RequestMapping("userReportToday")
    @ResponseBody
    public JSONPObject userReportToday(String callback) {
        Date startDate = DateConvertUtils.getDateStart(new Date());
        List<ProcessUserReport> reportList = statisticsProcessUser(startDate, DateConvertUtils.addDay(startDate, 1));

        return new JSONPObject(callback, Message.success(CollectionUtils.isEmpty(reportList) ? null : reportList.get(0)));
    }

    /**
     * 统计接待用户数
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return
     */
    @RequestMapping("processUserReport")
    @ResponseBody
    public Message processUserReport(@DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date startDate,
                                     @DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date endDate) {
        logger.info("【统计接待用户数】 startDate={}, endDate={}", DateConvertUtils.format(startDate),
                DateConvertUtils.format(endDate));
        List<ProcessUserReport> reportList = statisticsProcessUser(startDate, endDate);
        if (CollectionUtils.isNotEmpty(reportList) && reportList.size() > 1) {
            reportList.sort((o1, o2) -> o2.getReportDate().compareTo(o1.getReportDate()));
        }
        return Message.success(reportList);
    }

    /**
     * 定时统计接待用户数
     */
    @Scheduled(cron = "0 0 1 ? * *")
    public void statisticsProcessUser() {
        logger.info("【统计接待用户数定时任务】开始执行");
        ProcessUserReport lastReport = processUserReportService.findLastReport();
        Date endDate = DateConvertUtils.getDateStart(new Date());
        Date startDate;
        if (lastReport != null) {
            startDate = DateConvertUtils.addDay(lastReport.getReportDate(), 1);
        } else {
            startDate = DateConvertUtils.addDay(endDate, -1);
        }
        List<ProcessUserReport> reportList = statisticsProcessUser(startDate, endDate);
        if (CollectionUtils.isNotEmpty(reportList)) {
            processUserReportService.saveBatch(reportList);
        }
        logger.info("【统计接待用户数定时任务】执行结束");
    }

    /**
     * 保存接待用户数报表
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return
     */
    @RequestMapping("saveProcessUserReport")
    @ResponseBody
    public Message saveProcessUserReport(@DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date startDate,
                                         @DateTimeFormat(pattern = DateConvertUtils.DATE_FORMAT) Date endDate) {
        Date today = DateConvertUtils.getDateStart(new Date());
        if (endDate.after(today)) {
            endDate = today;
        }
        processUserReportService.deleteByReportDate(startDate, endDate);
        List<ProcessUserReport> reportList = statisticsProcessUser(startDate, endDate);
        if (CollectionUtils.isNotEmpty(reportList)) {
            processUserReportService.saveBatch(reportList);
        }
        return Message.success(null);
    }

    private List<ProcessUserReport> statisticsProcessUser(Date startDate, Date endDate) {
        Map<Date, ProcessUserReportWrapper> wrapperMap = new HashMap<>();
        processChatRecord(wrapperMap, startDate, endDate);
        if (wrapperMap.size() == 0) {
            return Collections.emptyList();
        }
        List<ChatRecord> recordList = chatRecordService.findUserRecordListByDate(startDate, endDate, Boolean.FALSE);
        if (CollectionUtils.isNotEmpty(recordList)) {
            for (ChatRecord record : recordList) {
                if (record.getUserId().toString().equals(record.getSendUserId())) {
                    continue;
                }
                ProcessUserReportWrapper wrapper = wrapperMap.get(DateConvertUtils.getDateStart(record.getCreateTime()));
                wrapper.addUserId(record.getUserId());
                ProcessUserReportWrapper.ProcessUserReportDetailWrapper detailWrapper =
                        wrapper.getDetailMap().get(record.getSendUserId());
                if (detailWrapper == null) {
                    detailWrapper = wrapper.addDetailWrapper(record.getSendUserId(), record.getSendNickName());
                }
                detailWrapper.addUserId(record.getUserId());
            }
        }
        List<ProcessUserReport> reportList = new ArrayList<>(wrapperMap.size());
        Date now = new Date();
        wrapperMap.forEach((reportDate, wrapper) -> {
            ProcessUserReport report = wrapper.build(reportDate);
            if (report.getUserCount() > 0) {
                report.setCreateTime(now);
                reportList.add(report);
            }
        });
        return reportList;
    }

    private void processChatRecord(Map<Date, ProcessUserReportWrapper> wrapperMap, Date startDate, Date endDate) {
        if (!endDate.after(startDate)) {
            return;
        }
        Date tempEndDate = DateConvertUtils.addDay(startDate, 1);
        if (tempEndDate.after(endDate)) {
            tempEndDate = endDate;
        }
        wrapperMap.put(startDate, new ProcessUserReportWrapper(startDate, tempEndDate));
        processChatRecord(wrapperMap, tempEndDate, endDate);
    }
}
